package com.edee.bigday.order.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.edee.bigday.order.constant.OrderConstant;
import com.edee.bigday.order.dao.OrderDao;
import com.edee.bigday.order.entity.OrderEntity;
import com.edee.bigday.order.entity.OrderItemEntity;
import com.edee.bigday.order.entity.PaymentInfoEntity;
import com.edee.bigday.order.enume.OrderStatusEnum;
import com.edee.bigday.order.feign.CartFeignService;
import com.edee.bigday.order.feign.CommodityFeignService;
import com.edee.bigday.order.feign.MemberFeignService;
import com.edee.bigday.order.feign.WmsFeignService;
import com.edee.bigday.order.interceptor.LoginUserInterceptor;
import com.edee.bigday.order.service.OrderItemService;
import com.edee.bigday.order.service.OrderService;
import com.edee.bigday.order.service.PaymentInfoService;
import com.edee.bigday.order.to.OrderCreateTo;
import com.edee.bigday.order.vo.*;
import com.edee.common.exception.NoStockException;
import com.edee.common.to.SeckillOrderTo;
import com.edee.common.to.mq.OrderTo;
import com.edee.common.utils.PageUtils;
import com.edee.common.utils.Query;
import com.edee.common.utils.R;
import com.edee.common.vo.MemberRespVo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    private ThreadLocal<OrderSubmitVo> submitVoThreadLocal = new ThreadLocal<>();

//    @Autowired
//    OrderDao orderDao;
//
//    @Autowired
//    OrderItemDao orderItemDao;

    @Autowired
    OrderItemService orderItemService;

    @Autowired
    CommodityFeignService commodityFeignService;

    @Autowired
    MemberFeignService memberFeignService;

    @Autowired
    CartFeignService cartFeignService;

    @Autowired
    WmsFeignService wmsFeignService;

    @Autowired
    ThreadPoolExecutor executor;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    PaymentInfoService paymentInfoService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public OrderConfirmVo comfirmOrder() throws ExecutionException, InterruptedException {
        OrderConfirmVo confirmVo = new OrderConfirmVo();
        MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();
        System.out.println("主线程----" + Thread.currentThread().getId());
        //获取之前的请求：
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {
            //异步任务，同步之前的请求数据：
            RequestContextHolder.setRequestAttributes(requestAttributes);
            System.out.println("member线程----" + Thread.currentThread().getId());
            //1、远程查询所有收获地址：
            List<MemberAddressVo> address = memberFeignService.getAddress(memberRespVo.getId());
            confirmVo.setAddress(address);
        }, executor);

        CompletableFuture<Void> cartFuture = CompletableFuture.runAsync(() -> {
            //异步任务，同步之前的请求数据：
            RequestContextHolder.setRequestAttributes(requestAttributes);
            System.out.println("cart线程----" + Thread.currentThread().getId());
            //2、远程查询购物车中选中的购物项：
            List<OrderItemVo> cartItems = cartFeignService.getCurrentUserCartItems();
            confirmVo.setItems(cartItems);
        }, executor).thenRunAsync(() -> {
            List<OrderItemVo> items = confirmVo.getItems();
            List<Long> collect = items.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
            R skuHasStock = wmsFeignService.getSkuHasStock(collect);
            //将数据进行转换：
            List<SkuStockVo> data = skuHasStock.getData(new TypeReference<List<SkuStockVo>>() {
            });
            //在页面遍历购物项信息的同时，还需要快速查到库存状态，所以，可以将库存状态data重新加工：
            if (data != null) {
                //将data加工成map放入confirmVo中：
                Map<Long, Boolean> map = data.stream().collect(Collectors.toMap(SkuStockVo::getSkuId, SkuStockVo::getHasStock));
                confirmVo.setStocks(map);
            }
        }, executor);
        //cartFeignService远程调用过程中，调用之前要构造请求，调用很多拦截器:
        // RequestInterceptor interceptor : requestInterceptors.
        //3、查询用户积分：
        Integer integration = memberRespVo.getIntegration();
        confirmVo.setIntegration(integration);
        //4、其它数据自动计算:

        //TODO 5、防重令牌（幂等性）
        String token = UUID.randomUUID().toString().replace("-", "");
        //服务器上保存令牌信息：
        redisTemplate.opsForValue().set(OrderConstant.USER_ORDER_TOKEN_PREFIX + memberRespVo.getId(), token, 30, TimeUnit.MINUTES);
        //页面上展示令牌信息：
        confirmVo.setOrderToken(token);

        //等待上面异步任务全部完成：
        CompletableFuture.allOf(addressFuture, cartFuture).get();
        return confirmVo;
    }

    //使用AopContext.currentProxy获取代理对象，示例代码：
    @Transactional(timeout = 30)
    public void a() {
        //使用代理对象进行本类调用：
        OrderServiceImpl orderItemService = (OrderServiceImpl) AopContext.currentProxy();
        orderItemService.b();
        orderItemService.c();
    }

    @Transactional(propagation = Propagation.REQUIRED, timeout = 2)
    public void b() {
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, timeout = 20)
    public void c() {
    }


    //    @GlobalTransactional
    @Transactional(isolation = Isolation.SERIALIZABLE)  //本地事务，在分布式系统中，只能控制本地事务的回滚，不能控制远程服务的回滚。(无法保证远程调用服务的一致性。)
    //必须使用分布式事务，最主要的原因就是网络问题+分布式机器。
    @Override
    public SubmitOrderResponseVo submitOrder(OrderSubmitVo vo) {
        submitVoThreadLocal.set(vo);
        SubmitOrderResponseVo responseVo = new SubmitOrderResponseVo();
        MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();
        responseVo.setCode(0);
        //创建订单、验令牌、验价、锁库存：
        //1、验证令牌：令牌的对比和删除必须保证原子性，此处和com/edee/bigday/commodity/service/impl/CategoryServiceImpl.java中一样采用lua脚本：
        //返回值0-令牌验证失败，1-令牌删除成功，亦即验证成功：
        String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                "then\n" +
                "    return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                "    return 0\n" +
                "end";
        String orderToken = vo.getOrderToken();
        //原子验证、删除令牌：
        Long result = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList(OrderConstant.USER_ORDER_TOKEN_PREFIX + memberRespVo.getId()), orderToken);
        if (result == 0L) {
            //令牌验证失败：
            responseVo.setCode(1);
            return responseVo;
        } else {
            //令牌验证成功：
            //创建订单、验令牌、验价、锁库存：
            //1、创建订单、订单项等信息：
            OrderCreateTo order = createOrder();
            //2、验价：
            //订单中计算所得的应付总额：
            BigDecimal payAmount = order.getOrder().getPayAmount();
            //页面提交的应付总价：
            BigDecimal payPrice = vo.getPayPrice();
            double abs = Math.abs(payAmount.subtract(payPrice).doubleValue());
            System.out.println("payAmount: " + payAmount + ", payPrice: " + payPrice + ", 价格差：" + abs);
            if (abs < 0.01) {
                //if (abs<500000){ //2021.08.07 03:16发现构建某个订单项时，错将orderItemEntity.getSkuPrice()写成了orderItemEntity.getCouponAmount()。
                //验价通过（金额相差在允许范围内）：
                //3、保存订单信息到数据库：
                saveOrder(order);
                //4、库存锁定：只要有异常，就回滚事务：
                //需要的数据：订单号、所有订单项(skuId、skuName、num)
                WareSkuLockVo wareSkuLockVo = new WareSkuLockVo();
                wareSkuLockVo.setOrderSn(order.getOrder().getOrderSn());
                List<OrderItemVo> locks = order.getOrderItems().stream().map(item -> {
                    OrderItemVo orderItemVo = new OrderItemVo();
                    orderItemVo.setSkuId(item.getSkuId());
                    orderItemVo.setCount(item.getSkuQuantity());
                    orderItemVo.setTitle(item.getSkuName());
                    return orderItemVo;
                }).collect(Collectors.toList());
                wareSkuLockVo.setLocks(locks);

                //TODO 远程锁定库存：
                //库存锁定成功后，可能会因为原因超时，导致订单回滚而库存不回滚。
                R r = wmsFeignService.orderLockStock(wareSkuLockVo);
                if (r.getCode() == 0) {
                    //库存锁定成功：
                    //将完整的订单信息放入响应中：
                    responseVo.setOrder(order.getOrder());

                    //5、远程扣减积分（暂时不做）
                    //模拟异常，可以让订单服务感知到，但无法让远程的库存服务感知到。
                    //问题：订单回滚，库存不回滚。
                    //int120 i = 10/0;  //模拟下单异常。

                    //订单创建成功，向MQ发送消息：
                    rabbitTemplate.convertAndSend("order-event-exchange", "order.create.order", order.getOrder());
                    //上的order.getOrder()，lfy首次错写为order。

                    return responseVo;
                } else {
                    //库存锁定失败，事务回滚:
                    throw new NoStockException(order.getOrder().getId());
                    //responseVo.setCode(3);
                    //return responseVo;
                    //后面改为如下，应该NoStockException也做了改动，282有剪辑，暂时没看到细节：
                     /*String msg = (String) r.get("msg");
                     throw new NoStockException(msg);*/
                }
            } else {
                //验价失败：
                responseVo.setCode(2);
                return responseVo;
            }
        }
//        String redisToken = redisTemplate.opsForValue().get(OrderConstant.USER_ORDER_TOKEN_PREFIX + memberRespVo.getId());
//        if (orderToken != null && orderToken.equals(redisToken)) {
//            //令牌验证通过：
//            redisTemplate.delete(OrderConstant.USER_ORDER_TOKEN_PREFIX + memberRespVo.getId());
//        } else {
//        }
    }

    @Override
    public OrderEntity getOrderEntityByOrderSn(String orderSn) {
        OrderEntity orderEntity = this.getOne(new QueryWrapper<OrderEntity>().eq("order_sn", orderSn));
        return orderEntity;
    }

    @Override
    public void closeOrder(OrderEntity entity) {
        //先查询当前订单的最新状态：
        OrderEntity orderEntity = this.getById(entity.getId());
        if (orderEntity.getStatus() == OrderStatusEnum.CREATE_NEW.getCode()) {
            //执行关单：
            OrderEntity orderToUpdate = new OrderEntity();
            orderToUpdate.setId(orderEntity.getId());
            orderToUpdate.setStatus(OrderStatusEnum.CANCLED.getCode());
            this.updateById(orderToUpdate); //lfy开始写的是this.updateById(orderEntity)，后修改为orderToUpdate。
            OrderTo orderTo = new OrderTo();
            BeanUtils.copyProperties(orderEntity, orderTo);
            //关单之后，向MQ发送一条消息：
            //rabbitTemplate.convertAndSend("order-event-exchange","order.release.other",orderEntity);
            try {
                //保证消息一定会发出去：可以将每条消息的发送做好日志记录，如，在数据库单独创建一张表mq_message（在表中保存每一条消息的详细信息）
                //定期扫描数据库，将发送失败的消息重新发送
                rabbitTemplate.convertAndSend("order-event-exchange", "order.release.other", orderTo);
            } catch (Exception e) {
                //发送失败的消息进行重发：
            }
        }
    }

    @Override
    public PayVo getOrderPay(String orderSn) {
        PayVo payVo = new PayVo();
        OrderEntity orderEntity = this.getOrderEntityByOrderSn(orderSn);
        BigDecimal payAmount = orderEntity.getPayAmount();
        BigDecimal payAmount2 = payAmount.setScale(2, BigDecimal.ROUND_UP);
        payVo.setTotal_amount(payAmount2.toString());
        payVo.setOut_trade_no(orderSn);
        List<OrderItemEntity> itemEntities = orderItemService.list(new QueryWrapper<OrderItemEntity>().eq("order_sn", orderSn));
        OrderItemEntity itemEntity = itemEntities.get(0);
        payVo.setSubject(orderEntity.getBillHeader() + itemEntity.getSkuName());
        payVo.setBody(orderEntity.getNote() + itemEntity.getSkuAttrsVals());
        return payVo;
    }

    @Override
    public PageUtils queryPageWithItem(Map<String, Object> params) {
        //从拦截器中获取当前用户：
        MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>().eq("member_id", memberRespVo.getId()).orderByDesc("id")
        );
        //将page中的订单列表取出，查询逐个订单包含的订单项，最后再封装为新的订单列表：
        List<OrderEntity> orderEntityList = page.getRecords().stream().map(order -> {
            List<OrderItemEntity> itemEntities = orderItemService.list(new QueryWrapper<OrderItemEntity>().eq("order_sn", order.getOrderSn()));
            order.setItemEntities(itemEntities);
            return order;
        }).collect(Collectors.toList());
        page.setRecords(orderEntityList);

        return new PageUtils(page);
    }

    /**
     * 处理支付宝的支付结果
     * @param vo
     * @return
     */
    @Override
    public String handlePayResult(PayAsyncVo vo) {
        //1、保存交易流水：
        PaymentInfoEntity infoEntity = new PaymentInfoEntity();
        infoEntity.setAlipayTradeNo(vo.getTrade_no());
        infoEntity.setOrderSn(vo.getOut_trade_no());
        infoEntity.setPaymentStatus(vo.getTrade_status());
        infoEntity.setCallbackTime(vo.getNotify_time());
        paymentInfoService.save(infoEntity);
        //2、修改订单状态信息:
        String tradeStatus = vo.getTrade_status();
        if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) {
            //支付成功：
            String tradeNo = vo.getOut_trade_no();
            this.baseMapper.updateOrderStatus(tradeNo, OrderStatusEnum.PAYED.getCode());
        }
        return "success";
    }

    @Override
    public void createSeckillOrder(SeckillOrderTo seckillOrderTo) {
        // TODO 保存订单信息
        OrderEntity orderEntity = new OrderEntity();
        BeanUtils.copyProperties(seckillOrderTo, orderEntity);
        orderEntity.setStatus(OrderStatusEnum.CREATE_NEW.getCode());
        BigDecimal multiply = seckillOrderTo.getSeckillPrice().multiply(new BigDecimal("" + seckillOrderTo.getNum()));
        orderEntity.setPayAmount(multiply);
        //保存订单信息
        this.save(orderEntity);
        //保存订单项信息
        OrderItemEntity orderItemEntity = new OrderItemEntity();
        orderItemEntity.setOrderSn(seckillOrderTo.getOrderSn());
        orderItemEntity.setSkuQuantity(seckillOrderTo.getNum());
        orderItemEntity.setSkuId(seckillOrderTo.getSkuId());
        orderItemEntity.setRealAmount(multiply);
        // TODO 远程调用commodityFeignService获取当前SPU的详细信息
        R spuInfoBySkuId = commodityFeignService.getSpuInfoBySkuId(seckillOrderTo.getSkuId());
        // 保存订单项信息
        orderItemService.save(orderItemEntity);
    }

    private void saveOrder(OrderCreateTo order) {
        //保存订单信息：
        OrderEntity orderEntity = order.getOrder();
        orderEntity.setModifyTime(new Date());
        this.save(orderEntity);
        //保存订单项信息：
        List<OrderItemEntity> orderItems = order.getOrderItems();
        orderItemService.saveBatch(orderItems);
    }

    private OrderCreateTo createOrder() {
        OrderCreateTo createTo = new OrderCreateTo();
        //1、生成订单号，使用MyBatis的IDWorker：
        String orderSn = IdWorker.getTimeId();
        //构建订单：
        OrderEntity orderEntity = buildOrder(orderSn);
        //2、获取到所有的订单项：
        List<OrderItemEntity> itemEntities = buildOrderItems(orderSn);
        //3、验价：
        //计算价格、积分、成长值相关的数据：
        computePrice(orderEntity, itemEntities);
        //之前未设置orderEntity和itemEntities到createTo中：
        createTo.setOrder(orderEntity);
        createTo.setOrderItems(itemEntities);
        return createTo;
    }

    private void computePrice(OrderEntity orderEntity, List<OrderItemEntity> itemEntities) {
        BigDecimal total = new BigDecimal("0.0");
        BigDecimal promotion = new BigDecimal("0.0");
        BigDecimal coupon = new BigDecimal("0.0");
        BigDecimal integration = new BigDecimal("0.0");
        BigDecimal gift = new BigDecimal("0.0");
        BigDecimal growth = new BigDecimal("0.0");
        //订单总金额：叠加每个订单项的金额：
        for (OrderItemEntity itemEntity : itemEntities) {
            //BigDecimal eachItemPrice = itemEntity.getSkuPrice().multiply(new BigDecimal(itemEntity.getSkuQuantity().toString()));
            promotion = promotion.add(itemEntity.getPromotionAmount());
            coupon = coupon.add(itemEntity.getCouponAmount());
            integration = integration.add(itemEntity.getIntegrationAmount());
            //total = total.add(itemEntity.getRealAmount());
            total = total.add(new BigDecimal(itemEntity.getRealAmount().toString()));
            gift = gift.add(new BigDecimal(itemEntity.getGiftIntegration().toString()));
            growth = growth.add(new BigDecimal(itemEntity.getGiftGrowth().toString()));
        }
        //1、订单价格相关的数据：
        orderEntity.setTotalAmount(total);
        //设置应付总额：
        orderEntity.setPayAmount(total.add(orderEntity.getFreightAmount()));
        orderEntity.setPromotionAmount(promotion);
        orderEntity.setCouponAmount(coupon);
        orderEntity.setIntegrationAmount(integration);
        //设置积分、成长值信息：
        orderEntity.setIntegration(gift.intValue());
        orderEntity.setGrowth(growth.intValue());
        //设置订单删除状态：
        orderEntity.setDeleteStatus(0);

    }

    private OrderEntity buildOrder(String orderSn) {
        OrderEntity entity = new OrderEntity();
        //设置订单号：
        entity.setOrderSn(orderSn);
        //设置会员Id:
        MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();
        entity.setMemberId(memberRespVo.getId());

        OrderSubmitVo orderSubmitVo = submitVoThreadLocal.get();
        //获取收货地址、运费信息：
        R fare = wmsFeignService.getFare(orderSubmitVo.getAddrId());
        //数据逆转FareVo：
        FareVo fareResp = fare.getData(new TypeReference<FareVo>() {
        });
        //设置运费金额：
        entity.setFreightAmount(fareResp.getFare());
        //设置收货人城市：
        entity.setReceiverCity(fareResp.getAddress().getCity());
        //设置收货人详细地址：
        entity.setReceiverDetailAddress(fareResp.getAddress().getDetailAddress());
        //设置收货人姓名、电话、邮编、省、区：
        entity.setReceiverName(fareResp.getAddress().getName());
        entity.setReceiverPhone(fareResp.getAddress().getPhone());
        entity.setReceiverPostCode(fareResp.getAddress().getPostCode());
        entity.setReceiverProvince(fareResp.getAddress().getProvince());
        entity.setReceiverRegion(fareResp.getAddress().getRegion());

        //设置订单的状态信息：
        entity.setStatus(OrderStatusEnum.CREATE_NEW.getCode());
        entity.setAutoConfirmDay(7);

        return entity;
    }

    /**
     * 构建所有订单项数据
     *
     * @return
     */
    private List<OrderItemEntity> buildOrderItems(String orderSn) {
        //最后确定每个购物项的价格（一旦确定，即使后台再调价，也是以此为准）：
        List<OrderItemVo> currentUserCartItems = cartFeignService.getCurrentUserCartItems();
        //可以参考line77、86使用异步任务，此处先不使用。
        //每一个OderItemVo最终都要构建成一个OderItem实体类，最后保存到数据库中。
        if (currentUserCartItems != null && currentUserCartItems.size() != 0) {
            List<OrderItemEntity> orderItemEntities = currentUserCartItems.stream().map(cartItem -> {
                OrderItemEntity orderItemEntity = buildOrderItem(cartItem);
                orderItemEntity.setOrderSn(orderSn);
                return orderItemEntity;
            }).collect(Collectors.toList());
            return orderItemEntities;
        }
        return null;
    }

    /**
     * 构建某个订单项
     *
     * @param cartItem
     * @return
     */
    private OrderItemEntity buildOrderItem(OrderItemVo cartItem) {
        OrderItemEntity orderItemEntity = new OrderItemEntity();
        //1、订单信息：订单号，在buildOrderItems()方法中已构建；
        //2、商品的Spu信息；
        R r = commodityFeignService.getSpuInfoBySkuId(cartItem.getSkuId());
        SpuInfoVo data = r.getData(new TypeReference<SpuInfoVo>() {
        });
        orderItemEntity.setSpuId(data.getId());
        orderItemEntity.setSpuName(data.getSpuName());
        orderItemEntity.setSpuBrand(data.getBrandId().toString());
        //orderItemEntity.setSpuPic();
        orderItemEntity.setCategoryId(data.getCatalogId());
        //3、商品的Sku信息；
        orderItemEntity.setSkuId(cartItem.getSkuId());
        orderItemEntity.setSkuName(cartItem.getTitle());
        orderItemEntity.setSkuPic(cartItem.getImage());
        orderItemEntity.setSkuPrice(cartItem.getPrice());
        String skuAttr = StringUtils.collectionToDelimitedString(cartItem.getSkuAttr(), ";");
        orderItemEntity.setSkuAttrsVals(skuAttr);
        orderItemEntity.setSkuQuantity(cartItem.getCount());
        //4、优惠信息（暂时忽略）；
        //5、积分信息：
        orderItemEntity.setGiftGrowth(cartItem.getPrice().multiply(new BigDecimal(cartItem.getCount().toString())).intValue());
        orderItemEntity.setGiftIntegration(cartItem.getPrice().multiply(new BigDecimal(cartItem.getCount().toString())).intValue());
        //6、该订单项的价格信息：
        orderItemEntity.setPromotionAmount(new BigDecimal("0"));
        orderItemEntity.setCouponAmount(new BigDecimal("0"));
        orderItemEntity.setIntegrationAmount(new BigDecimal("0"));
        //当前订单项的实际金额：
        //BigDecimal originalPrice = orderItemEntity.getCouponAmount().multiply(new BigDecimal(orderItemEntity.getSkuQuantity().toString()));
        //上面错将orderItemEntity.getSkuPrice()写成了orderItemEntity.getCouponAmount()  ======2021.08.07 03:14排查发现。
        BigDecimal originalPrice = orderItemEntity.getSkuPrice().multiply(new BigDecimal(orderItemEntity.getSkuQuantity().toString()));
        BigDecimal subtract = originalPrice.subtract(orderItemEntity.getPromotionAmount()).subtract(orderItemEntity.getCouponAmount()).subtract(orderItemEntity.getIntegrationAmount());
        orderItemEntity.setRealAmount(subtract);
        return orderItemEntity;
    }

}